/**
 * JZ UnoCSS - CSS监视器模块
 * 监视文件变化并自动更新CSS
 * @version 1.1.0
 * @author jz
 */

import { generateCSS } from '../core/generator.js';
import { utils } from '../utils/utils.js';
import { updateCSSFile } from '../processors/processor.js';

// 全局变量
let isWatching = false;
let watchTimer = null;
let generatedClasses = new Set(); // 缓存已生成的类名
let cssCache = new Map(); // CSS缓存

// 尝试加载可选的依赖模块
let glob = null;
try {
    glob = require('glob');
} catch (e) {
    // glob模块不可用，将使用备用方法
}

// 检查运行环境
let isNodeEnvironment = false;
try {
    require('fs');
    isNodeEnvironment = true;
} catch (e) {
    // 当前环境不支持Node.js模块
}

/**
 * CSS监视器类
 */
export class CSSWatcher {
    constructor(options = {}) {
        this.options = {
            watchPaths: options.watchPaths || ['**/*.uvue'],
            cssOutputPath: options.cssOutputPath || 'uni_modules/jz-unocss-uvue/main.css',
            debounceTime: options.debounceTime || 300,
            ...options
        };
        
        this.isWatching = false;
        this.watchTimer = null;
        this.generatedClasses = new Set();
        this.cssCache = new Map();
    }
    
    /**
     * 启动CSS监视器
     */
    start() {
        if (this.isWatching) {
            return;
        }
        
        this.isWatching = true;
    }
    
    /**
     * 停止CSS监视器
     */
    stop() {
        if (!this.isWatching) {
            return;
        }
        
        this.isWatching = false;
        
        if (this.watchTimer) {
            clearTimeout(this.watchTimer);
            this.watchTimer = null;
        }
    }
    
    /**
     * 处理文件变化
     * @param {string} filePath - 文件路径
     * @param {string} content - 文件内容
     */
    async handleFileChange(filePath, content) {
        if (!this.isWatching) {
            return;
        }
        
        // 防抖处理
        if (this.watchTimer) {
            clearTimeout(this.watchTimer);
        }
        
        this.watchTimer = setTimeout(() => {
            this.processFile(filePath, content);
        }, this.options.debounceTime);
    }
    
    /**
     * 处理单个文件
     * @param {string} filePath - 文件路径
     * @param {string} content - 文件内容
     */
    processFile(filePath, content) {
        try {
            const classNames = this.extractClassNames(content);
            
            if (classNames.length > 0) {
                const result = this.updateCSS(classNames);
                if (result) {
                    // CSS更新成功
                } else {
                    // 未生成新CSS
                }
            }
        } catch (error) {
            console.error('[JZ UnoCSS] 更新CSS时出错:', error);
        }
    }
    
    /**
     * 从内容中提取类名
     * @param {string} content - 文件内容
     * @returns {string[]} 类名数组
     */
    extractClassNames(content) {
        const classNames = new Set();
        
        // 匹配 class="..." 中的类名
        const classRegex = /class\s*=\s*["']([^"']+)["']/g;
        let match;
        
        while ((match = classRegex.exec(content)) !== null) {
            const classString = match[1];
            const classes = classString.split(/\s+/).filter(cls => cls.trim());
            classes.forEach(cls => {
                if (cls.trim()) {
                    classNames.add(cls.trim());
                }
            });
        }
        
        // 匹配 :class="..." 中的类名
        const dynamicClassRegex = /:class\s*=\s*["']([^"']+)["']/g;
        while ((match = dynamicClassRegex.exec(content)) !== null) {
            const classString = match[1];
            const literalClasses = classString.match(/['"]([^'"]+)['"]/g);
            if (literalClasses) {
                literalClasses.forEach(literal => {
                    const cls = literal.slice(1, -1);
                    if (cls.trim()) {
                        classNames.add(cls.trim());
                    }
                });
            }
        }
        
        return Array.from(classNames);
    }
    
    /**
     * 更新CSS
     * @param {string[]} classNames - 类名数组
     * @param {boolean} forceRegenerate - 是否强制重新生成
     * @returns {boolean} 是否生成了新CSS
     */
    updateCSS(classNames, forceRegenerate = false) {
        if (!classNames || classNames.length === 0) {
            return false;
        }
        
        const newClasses = [];
        const newCSSRules = [];
        
        if (forceRegenerate) {
            // 强制重新生成模式: 清除已生成类名集合
            this.generatedClasses.clear();
            this.cssCache.clear();
        }
        
        // 处理每个类名
        for (const className of classNames) {
            
            // 检查是否已经生成过
            if (!forceRegenerate && this.generatedClasses.has(className)) {
                continue;
            }
            
            // 检查缓存
            if (this.cssCache.has(className)) {
                const cachedCSS = this.cssCache.get(className);
                newCSSRules.push(cachedCSS);
                newClasses.push(className);
                this.generatedClasses.add(className);
                continue;
            }
            
            // 生成CSS
            try {
                const styles = generateCSS(className, this.options);
                
                if (styles && typeof styles === 'object' && Object.keys(styles).length > 0) {
                    // 编码类名
                    const encodedClassName = utils.encodeClassNameForUvue(className);
                    
                    // 生成CSS规则
                    const cssProps = Object.entries(styles)
                        .filter(([prop]) => !prop.startsWith('__'))
                        .map(([prop, value]) => `  ${prop}: ${value};`)
                        .join('\n');
                    
                    if (cssProps) {
                        const cssRule = `.${encodedClassName} {\n${cssProps}\n}`;
                        
                        // 缓存CSS
                        this.cssCache.set(className, cssRule);
                        newCSSRules.push(cssRule);
                        newClasses.push(className);
                        this.generatedClasses.add(className);
                    }
                } else if (typeof styles === 'string') {
                    // 直接是CSS字符串（如条件编译CSS）
                    this.cssCache.set(className, styles);
                    newCSSRules.push(styles);
                    newClasses.push(className);
                    this.generatedClasses.add(className);
                }
            } catch (generateError) {
                console.error(`[JZ UnoCSS] 为 ${className} 生成CSS时出错:`, generateError);
            }
        }
        
        // 写入CSS文件
        if (newCSSRules.length > 0) {
            try {
                const cssContent = newCSSRules.join('\n\n') + '\n';
                return this.writeCSS(cssContent);
            } catch (error) {
                console.error('[JZ UnoCSS] 写入CSS失败:', error);
                return false;
            }
        }
        
        return false;
    }
    
    /**
     * 写入CSS到文件
     * @param {string} cssContent - CSS内容
     * @returns {boolean} 是否成功写入
     */
    writeCSS(cssContent) {
        if (!cssContent) {
            return false;
        }
        
        try {
            // 尝试使用Node.js环境的文件操作
            if (isNodeEnvironment) {
                let fs, path;
                try {
                    fs = require('fs');
                    path = require('path');
                } catch (requireError) {
                    console.warn('[JZ UnoCSS] ⚠️ Node.js模块不可用:', requireError.message);
                    return false;
                }
                
                const cssFilePath = this.options.cssOutputPath;
                const dir = path.dirname(cssFilePath);
                
                // 确保目录存在
                if (!fs.existsSync(dir)) {
                    fs.mkdirSync(dir, { recursive: true });
                }
                
                // 读取现有内容
                let existingContent = '';
                if (fs.existsSync(cssFilePath)) {
                    existingContent = fs.readFileSync(cssFilePath, 'utf-8');
                } else {
                    // CSS文件不存在，将创建新文件
                }
                
                // 更新CSS内容
                let finalContent;
                
                // 查找动态CSS部分
                const dynamicStartMarker = '/* === JZ UnoCSS 动态生成的CSS (请勿手动编辑) === */';
                const dynamicEndMarker = '/* === JZ UnoCSS 动态生成结束 === */';
                
                const startIndex = existingContent.indexOf(dynamicStartMarker);
                const endIndex = existingContent.indexOf(dynamicEndMarker);
                
                if (startIndex !== -1 && endIndex !== -1) {
                    // 更新现有动态CSS部分
                    const beforeDynamic = existingContent.substring(0, startIndex);
                    const afterDynamic = existingContent.substring(endIndex + dynamicEndMarker.length);
                    
                    finalContent = beforeDynamic + 
                                 dynamicStartMarker + '\n' + 
                                 cssContent + '\n' + 
                                 dynamicEndMarker + 
                                 afterDynamic;
                } else {
                    // 添加新的动态CSS部分
                    finalContent = existingContent + 
                                 (existingContent ? '\n\n' : '') + 
                                 dynamicStartMarker + '\n' + 
                                 cssContent + '\n' + 
                                 dynamicEndMarker;
                }
                
                // 写入文件
                fs.writeFileSync(cssFilePath, finalContent, 'utf-8');
                
                // 验证写入结果
                const writtenContent = fs.readFileSync(cssFilePath, 'utf-8');
                if (writtenContent.length !== finalContent.length) {
                    // 重新写入CSS文件
                    fs.writeFileSync(cssFilePath, finalContent, 'utf-8');
                }
                
                return true;
            } else {
                console.warn('[JZ UnoCSS] ⚠️ 文件系统模块不可用，无法写入文件系统');
                return false;
            }
        } catch (error) {
            console.error('[JZ UnoCSS] ❌ 写入CSS文件失败:', error.message);
            console.error('[JZ UnoCSS] 错误详情:', error);
            return false;
        }
    }
    
    /**
     * 清除缓存
     */
    clearCache() {
        this.generatedClasses.clear();
        this.cssCache.clear();
    }
}

// 创建全局CSS监视器实例
export const cssWatcher = new CSSWatcher();

// CSS监视器工具函数
export const cssWatcherUtils = {
    /**
     * 手动触发CSS生成
     * @param {string[]} classNames - 类名数组
     * @param {Object} options - 选项
     * @returns {boolean} 是否成功生成
     */
    generateCSS: (classNames, options = {}) => {
        const watcher = new CSSWatcher(options);
        return watcher.updateCSS(classNames, true);
    },
    
    /**
     * 从代码中提取类名并生成CSS
     * @param {string} code - 源代码
     * @param {Object} options - 选项
     * @returns {boolean} 是否成功生成
     */
    generateCSSFromCode: (code, options = {}) => {
        const watcher = new CSSWatcher(options);
        const classNames = watcher.extractClassNames(code);
        
        if (classNames.length > 0) {
            return watcher.updateCSS(classNames);
        }
        
        return false;
    },
    
    /**
     * 扫描项目并生成CSS
     * @param {Object} options - 选项
     * @returns {Promise<boolean>} 是否成功生成
     */
    scanAndGenerateCSS: async (options = {}) => {
        // 扫描项目进行CSS生成...
        
        if (!isNodeEnvironment) {
            return false;
        }
        
        try {
            let fs, path, glob;
            try {
                fs = require('fs');
                path = require('path');
                
                try {
                    glob = require('glob');
                } catch (e) {
                    // 检测到HBuilderX环境，正在搜索项目根目录...
                    glob = null;
                }
            } catch (e) {
                return false;
            }
            
            // 检测项目根目录
            let realProjectPath = process.cwd();
            
            // 检查是否在uni_modules中
            if (realProjectPath.includes('uni_modules')) {
                // 向上查找项目根目录
                let currentPath = realProjectPath;
                while (currentPath !== path.dirname(currentPath)) {
                    if (fs.existsSync(path.join(currentPath, 'pages.json'))) {
                        realProjectPath = currentPath;
                        break;
                    }
                    currentPath = path.dirname(currentPath);
                }
                
                // 通过检测找到项目根目录: ${realProjectPath}
            } else {
                // 检测到uni_modules上下文，使用项目根目录: ${realProjectPath}
            }
            
            // 验证项目根目录
            if (!fs.existsSync(realProjectPath)) {
                console.warn(`[JZ UnoCSS] 项目根目录不存在: ${realProjectPath}`);
                return false;
            }
            
            // 扫描文件
            const scanPaths = options.watchPaths || ['**/*.uvue'];
            const allClassNames = new Set();
            
            for (const pattern of scanPaths) {
                const files = glob ? glob.sync(pattern, { cwd: realProjectPath }) : [];
                
                for (const file of files) {
                    const filePath = path.join(realProjectPath, file);
                    try {
                        const content = fs.readFileSync(filePath, 'utf-8');
                        const watcher = new CSSWatcher(options);
                        const classNames = watcher.extractClassNames(content);
                        classNames.forEach(cls => allClassNames.add(cls));
                    } catch (error) {
                        console.warn(`[JZ UnoCSS] 读取文件失败 ${filePath}:`, error.message);
                    }
                }
            }
            
            if (allClassNames.size > 0) {
                const watcher = new CSSWatcher(options);
                return watcher.updateCSS(Array.from(allClassNames), true);
            }
            
            return false;
        } catch (error) {
            console.error('[JZ UnoCSS] 扫描生成CSS失败:', error.message);
            return false;
        }
    }
};

// 类和常量已在定义时导出，无需重复导出 